﻿using System;
using System.Configuration;
using System.Collections.Generic;
using System.Web.Services;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Linq;
using Microsoft.SqlServer.Management.Smo;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Globalization;
using Sharp;
using System.IO;
using System.Reflection;


namespace Sharp.Build
{
    //[HttpHandler("/FormPageBuilder")]
    public partial class FormPageBuilder : IHttpHandler
    {
        Template template { get; set; }

        public FormPageBuilder() 
        {
            HttpContext context = HttpContext.Current;

            context.Response.Clear();
            context.Response.ContentType = "text/plain";
            context.Response.Buffer = false;

            String connstr = ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;

            using (SqlConnection conn = new SqlConnection(connstr))
            {
                conn.Open();
                Server sv = new Server(new Microsoft.SqlServer.Management.Common.ServerConnection(conn));

                // sv.SetDefaultInitFields(typeof(StoredProcedureParameter), new String[] { "IsOutputParameter", "Name", "DataType", "Length" });
                sv.SetDefaultInitFields(typeof(StoredProcedure), "IsSystemObject");

                // Parse the coonectionstring to a dictionary
                String dbname = connstr.Split(";").Cast<String>().ToDictionary(x => x.Split("=")[0], x => x.Split("=")[1])["Initial catalog"];
                Database db = sv.Databases[dbname];

                foreach (Table tbl in db.Tables)
                {

                    String form = "/templates/" + tbl.Name + "-form.htm";
                    String page = "/templates/" + tbl.Name + "-page.cs";
                    if (File.Exists(context.Server.MapPath(page)))
                    {
                        if (File.Exists(context.Server.MapPath(page + ".bak")))
                            File.Delete(context.Server.MapPath(page + ".bak"));
                        File.Copy(context.Server.MapPath(page), context.Server.MapPath(page + ".bak"));
                    }
                    if (File.Exists(context.Server.MapPath(form)))
                    {
                        if (File.Exists(context.Server.MapPath(form + ".bak")))
                            File.Delete(context.Server.MapPath(form + ".bak"));
                        File.Copy(context.Server.MapPath(form), context.Server.MapPath(form + ".bak"));
                    }
                    //TextWriter tw = new StreamWriter(context.Server.MapPath("/objects/" + Query["name"]+ ".cs"));


                    template = new Template(Properties.Resources.Page);
                    BuildPage(db, tbl.Name.ToLower());
                    File.WriteAllText(context.Server.MapPath(page), template.ToString());
                      
                    File.WriteAllText(context.Server.MapPath(form),  BuildForm(db, tbl.Name.ToLower()));
                }
            }
        }



        public String BuildForm(Database db, string tablename)
        {

            String form = Properties.Resources.Form; // Cached.GetFile("../Builders/form.htm"); 

            StringBuilder formli = new StringBuilder();
            StringBuilder rules = new StringBuilder();

            foreach (StoredProcedureParameter param in db.StoredProcedures["usp_" + tablename + "_ups"].Parameters)
            {

                if (param.DataType.SqlDataType == SqlDataType.Bit)
                {
                    String liCheck = " <li><label class=\"checkbox\" for=\"{0}\"><input name=\"{0}\" id=\"{0}\" class=\"checkbox\" type=\"checkbox\" token=\"[%{0}%]\" value=\"1\" /></label{0}</li>";
                    formli.AppendLine( string.Format(liCheck , param.Name.Replace("@", "")));
                } 
                else
                {
                    if ((param.Properties["Length"].Value.ToString().ToInt(0) > 250 || param.Properties["Length"].Value.ToString().ToInt(0) == -1) && param.DataType.ConvertToCLR().Like("String"))
                    {
                        String liInput = @" <li><label for=""{0}"">{1}:</label>
					            <textarea id=""{0}"" name=""{0}""  {2}  cols=""38"" rows=""3"" title=""{1}"">[%{0}%]</textarea></li>";
                        formli.AppendLine(string.Format(liInput, param.Name.Replace("@", ""), param.Name.Replace("@", "").Replace("_", " ").Capitalize(),  param.Properties["Length"].Value.ToString().ToInt(0) == -1 ? "" :"maxvalue=\"" + param.Properties["Length"].Value + "\""));
                    }
                    else
                    { 
                        String liInput = @" <li><label for=""{0}"">{1}:</label>
					            <input class=""text"" {2} name=""{0}"" id=""{0}"" type=""text""  title=""{1}"" value=""[%{0}%]"" /></li>";
                        formli.AppendLine(string.Format(liInput, param.Name.Replace("@", ""), param.Name.Replace("@", "").Replace("_", " ").Capitalize(), param.DataType.ConvertToCLR().Like("String") ? "maxvalue=\"" + param.Properties["Length"].Value + "\"" : ""));

                    }
                }
                if (param.DataType.ConvertToCLR().Like("String"))
                    rules.AppendLine(string.Format("{0}: {{ required: true}},", param.Name.Replace("@", "")));
                else
                    rules.AppendLine(string.Format("{0}: {{ required: true }},", param.Name.Replace("@", ""))); 
                
            }

            form = form.Replace("[%utablename%]", tablename.Capitalize());
            form = form.Replace("[%tablename%]", tablename); 
            form = form.Replace("[%rules%]", rules.ToString()); 
            form = form.Replace("[%formli%]", formli.ToString()); 

            return form;
        }

        public void BuildPage(Database db, string tablename)
        { 
            foreach (StoredProcedureParameter param in db.StoredProcedures["usp_" + tablename + "_ups"].Parameters)
            {
                if (param.DataType.SqlDataType == SqlDataType.Int)
                {
                    template.Append("upsert", string.Format("\n\t\t\t\t\t_{1}.{0} = sb.TestPattern(Form[\"{0}\"], StringType.Numeric, \"invalid {0}\").ToInt(0);", param.Name.Replace("@", ""), tablename));
                    template.Append("exists", string.Format("\n\t\t\t\t\ttemplate.Set(\"{0}\", _{1}.{0});", param.Name.Replace("@", ""), tablename)); 
                }
                else if (param.DataType.SqlDataType == SqlDataType.BigInt)
                {
                    template.Append("upsert", string.Format("\n\t\t\t\t\t_{1}.{0} = sb.TestPattern(Form[\"{0}\"], StringType.Numeric, \"invalid {0}\").ToLong(0);", param.Name.Replace("@", ""), tablename));
                    template.Append("exists", string.Format("\n\t\t\t\t\ttemplate.Set(\"{0}\", _{1}.{0});", param.Name.Replace("@", ""), tablename));
                }
                else if (param.DataType.SqlDataType == SqlDataType.Bit)
                {
                    template.Append("upsert", string.Format("\n\t\t\t\t\t_{1}.{0} = Form[\"{0}\"].ToBool();", param.Name.Replace("@", ""), tablename));
                    template.Append("exists", string.Format("\n\t\t\t\t\ttemplate.Set(\"{0}\", _{1}.{0}.ToChecked());", param.Name.Replace("@", ""), tablename));
                }
                else
                {
                    template.Append("upsert", string.Format("\n\t\t\t\t\t_{1}.{0} = sb.TestEmpty(Form[\"{0}\"], \"invalid {0}\");", param.Name.Replace("@", ""), tablename));
                    template.Append("exists", string.Format("\n\t\t\t\t\ttemplate.Set(\"{0}\", _{1}.{0});", param.Name.Replace("@", ""), tablename));
                }
            }
            
            template.Set("utablename", tablename.Capitalize());
            template.Set("tablename", tablename);
        }

        #region IHttpHandler Members

        public bool IsReusable
        {
            get { return false; }
        }

        public void ProcessRequest(HttpContext context)
        {
            
        }

        #endregion
    }

    public static class SQLExtentions
    {
        public static String ConvertToCLR(this DataType datatype)
        {
            String rtrn = "String";
            switch (datatype.SqlDataType)
            {
                case SqlDataType.BigInt: rtrn = "Int64"; break;
                case SqlDataType.Binary: rtrn = "Byte[]"; break;
                case SqlDataType.Bit: rtrn = "Boolean"; break;
                case SqlDataType.Char: rtrn = "String"; break;
                case SqlDataType.DateTime: rtrn = "DateTime"; break;
                case SqlDataType.Decimal: rtrn = "Decimal"; break;
                case SqlDataType.Float: rtrn = "Double"; break;
                case SqlDataType.Image: rtrn = "String"; break;
                case SqlDataType.Int: rtrn = "Int32"; break;
                case SqlDataType.Money: rtrn = "Decimal"; break;
                case SqlDataType.NChar: rtrn = "String"; break;
                case SqlDataType.NText: rtrn = "String"; break;
                case SqlDataType.NVarChar: rtrn = "String"; break;
                case SqlDataType.NVarCharMax: rtrn = "String"; break;
                case SqlDataType.None: rtrn = "String"; break;
                case SqlDataType.Numeric: rtrn = "Decimal"; break;
                case SqlDataType.Real: rtrn = "Single"; break;
                case SqlDataType.SmallDateTime: rtrn = "DateTime"; break;
                case SqlDataType.SmallInt: rtrn = "Int16"; break;
                case SqlDataType.SmallMoney: rtrn = "Decimal"; break;
                case SqlDataType.SysName: rtrn = "String"; break;
                case SqlDataType.Text: rtrn = "String"; break;
                case SqlDataType.Timestamp: rtrn = "String"; break;
                case SqlDataType.TinyInt: rtrn = "Byte"; break;
                case SqlDataType.UniqueIdentifier: rtrn = "Guid"; break;
                case SqlDataType.UserDefinedDataType: rtrn = "String"; break;
                case SqlDataType.UserDefinedType: rtrn = "String"; break;
                case SqlDataType.VarBinary: rtrn = "Byte[]"; break;
                case SqlDataType.VarBinaryMax: rtrn = "Byte[]"; break;
                case SqlDataType.VarChar: rtrn = "String"; break;
                case SqlDataType.VarCharMax: rtrn = "String"; break;
                case SqlDataType.Variant: rtrn = "String"; break;
                case SqlDataType.Xml: rtrn = "String"; break;
                default: break;
            }
            return rtrn;
        }

    }
}

	
 		
 		